#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_

#include <stdlib.h>

#include "buffer.h"		/* this module depends on 'buffer' module */
#include "funcs.h"		/* this module depends on 'funcs' module */

/***************************************************
 * user customize
 ***************************************************/

/* ---- memory allocating method ---- */
#define PB_MALLOC(size)		malloc(size)
#define PB_FREE(ptr)        free(ptr)


/* ---- logging method ---- */
#include "log.h"
#define ERROR_LOG		WLOG_ERR


/* ---- whether open debug ---- */
//#define MC_DEBUG	

/* ---- the buffer length ---- */
#define MAX_FIELDS			50		/* max fields split by seperator */
#define MAX_SPLITER_LEN		50		/* max length of the spliter */




/***************************************************
 * internal definition. DO NOT MODIFY
 ***************************************************/

/* return value for current state of protocol entry */
#define READING_HEADER		1		/* now protocol_basic is reading request header */
#define READING_ENTITY		2		/* now protocol_basic is reading request entity(depends on length speicified by user) */
#define READING_FINISH		0		/* a request is completely read */
#define ERROR				-1		/* some error occured. reading stopped. refer to log file */	
#define LEN_BUF_AGAIN		-2		/* fixed-length-buffer is full. buffer transfer is called and you need buffer again */


/* return value of protocol_responser */
#define P_RESPONSER_ERR		-1
#define P_RESPONSER_OK		0


/* definations of memcache console */
#define READ_HEADER		1	/* to read request header */
#define READ_ENTITY		2	/* to read request entity */
#define SUBMIT			3	/* reserved */
#define RESPONSE		4	/* reserved */
#define END				5	/* reading end */


/*--------------------------------------------------------------------*/


/* basic TCP request (header & entity) */
typedef struct request_header
{
	char *fields[MAX_FIELDS];	/* the fields of the request */
	int fields_count;			/* indicates there are how many fields has been separated */
}REQ_HEADER;


typedef struct request_entity
{
	void *entity_entry;		/* the entry pointer to entity (may be binary data) */
	size_t entity_len;		/* indicates what the size is of the entity data */
}REQ_ENTITY;


/*--------------------------------------------------------------------*/


/* functions' pointer */
typedef void *BUF_TRANSFER(char *, size_t);

/* memcache at-all-time used struct,
 * which contains all the neccesary information all over the process */
typedef struct protocol_handler
{
	/* resources part */
	REQ_HEADER req_header;				/* instance of REQ_HEADER */
	REQ_ENTITY req_entity;				/* instance of RRQ_ENTITY */
	CONDITION_BUF *cdt_buf_handler;		/* cdt buffer pointer */
	LENGTH_BUF *len_buf_handler;		/* len buffer pointer */
	char spliter[MAX_SPLITER_LEN + 1];
	
	/* buffer transfer, which always be called when buffer is full */
	BUF_TRANSFER *buf_transfer;
	/* protocol responser, which always be called when an entire request is read */
	void *p_responser;
	/* protocol header parser, which always be called when an entire header is read */
	void *header_parser;
	
	void *user_data;		/* pointer of user's data */
	void *custom_p1;		/* for user to customize (mount point 1) */
	void *custom_p2;		/* for user to customize (mount point 2) */
	void *custom_p3;		/* for user to customize (mount point 3) */
	void *custom_p4;		/* for user to customize (mount point 4) */
	
	/* console part */
	int mc_console;		/* save the READ_HEADER or READ_ENTITY or .... */

    int is_submit;
	
}PROTOCOL;


typedef int P_RESPONSER(PROTOCOL *);
typedef ssize_t HEADER_PARSER(PROTOCOL *);

/*--------------------------------------------------------------------*/
 

/* public functions */
PROTOCOL * 
pb_init(const char *header_term, const char *spliter, BUF_TRANSFER *buf_transfer, 
				P_RESPONSER *p_responser, HEADER_PARSER *header_parser);
				
int protocol_entry(PROTOCOL *handler, char *data, size_t len);
int protocol_clean(PROTOCOL *handler);
int protocol_reset(PROTOCOL *handler);

/* public macros */
#define get_header_fields(handler)		handler->req_header.fields			/* (char **) 	*/
#define get_header_count(handler)		handler->req_header.fields_count	/* (int) 		*/
#define get_entity_entry(handler)		handler->req_entity.entity_entry	/* (void *) 	*/
#define get_entity_len(handler)			handler->req_entity.entity_len		/* (size_t) 	*/

#define set_user_data(handler, data)	(handler->user_data = data)			/* (void* = &data) */
#define get_user_data(handler)			handler->user_data					/* (void* = &data) */

#define set_custom_p1(handler, data)	(handler->custom_p1 = data)			/* (void* = &data) */
#define set_custom_p2(handler, data)	(handler->custom_p2 = data)			/* (void* = &data) */
#define set_custom_p3(handler, data)	(handler->custom_p3 = data)			/* (void* = &data) */
#define set_custom_p4(handler, data)	(handler->custom_p4 = data)			/* (void* = &data) */
#define get_custom_p1(handler)			handler->custom_p1			/* (void* = &data) */
#define get_custom_p2(handler)			handler->custom_p2			/* (void* = &data) */
#define get_custom_p3(handler)			handler->custom_p3			/* (void* = &data) */
#define get_custom_p4(handler)			handler->custom_p4			/* (void* = &data) */



									

#endif

